# _*_ coding:utf-8 _*_
# 开发团队: Mavericks
# 开发人员：Maverick·Ming
# 开发IDE： PyCharm
#   项目名：DouBanSpider
#   文件名：testBs4.py
# 开发时间：2021/3/31 11:55

"""
BeautifulSoup将复杂的HTML文档，转换成一个复杂的树形结构
每个节点都是Python对象，所有的对象可以归纳为4种
- BeautifulSoup
- Tag
- NavigableString
- Comment
"""
from pprint import pprint
import re

from bs4 import BeautifulSoup
import data
# 打开文件，让其分析
with open('../data/baidu.html', 'rb') as file:
    html = file.read().decode('utf-8')
    bs = BeautifulSoup(html, 'html.parser')

    # 第一种类型，bs4.BeautifulSoup，包含了整个网页内容的文档
    # print(type(bs))  # <class 'bs4.BeautifulSoup'>
    # print(bs.name)  # [document],整个文档
    # print(bs)

    # 第二种类型，bs4.element.Tag，代表网页里边的标签Tag
    # 解析标签, 整个标签打印
    # print(bs.title, type(bs.title))  # 拿到一个标签，以及标签内的内容
    # print(bs.a)  # 但是只拿到第一个标签，就停止了
    # print(bs.head)  # <class 'bs4.element.Tag'>

    # 标签里的所有属性值
    # print(bs.a.attrs, type(bs.a.attrs))  # <class 'dict'>

    # 第三种类型，bs4.element.NavigableString，标签Tag里的字符串
    # 只想要标签内的内容
    # print(bs.title.string, type(bs.title.string))
    # print(bs.a.string, type(bs.a.string))
    # <class 'bs4.element.NavigableString'>
    # Navigable string 标签里的字符串

    # 第四种类型,<class 'bs4.element.Comment'> , 注释内容<!-- -->
    # print(bs.a.string, type(bs.a.string))

    # -------------------------------------------------------------------

    # BeautifulSoup应用

    # 文档的遍历

    # pprint(bs.head.contents)
    # print(bs.head.contents[1])  # 遍历该文件树的第二个文件
    # 此处的contents就是四种对象的特定属性，利用这些属性的功能，可以遍历文档树，搜索文档树
    # 更多内容，阅读文档

    # 文档的搜索

    # 1.find_all() 查找所有的a标签
    # 字符串过滤：会查找与字符串完全匹配的内容
    # t_list = bs.find_all('a')
    # pprint(t_list)

    # 正则表达式搜索:使用search()方法来匹配内容
    # t_list = bs.find_all(re.compile('a'))  #编译一个正则表达式对象,搜索所有符合正则表达式包含a的内容
    # pprint(t_list)

    # 利用方法搜索:传入一个函数(方法),根据函数的要求搜索内容
    # def name_is_exists(tag):
    #     return tag.has_attr("name")  # 搜索一个tag,包含有name属性的tag

    # 可以按照自己定义的内容查询
    # t_list = bs.find_all(name_is_exists)
    # pprint(t_list)

    # 2.kwargs 参数
    # t_list = bs.find_all(id='head')  # 不仅仅是一个规则,还可以是参数,根据属性里的参数来搜索
    # t_list = bs.find_all(class_=True)  # 包含class属性的都显示 class_加了个下划线是为了防止与python标识符冲突
    # t_list = bs.find_all(href='http://news.baidu.com')  # 按链接查找
    # pprint(t_list)

    # 3.text  参数  text代表标签里的字符串
    # t_list = bs.find_all(text='hao123')  # 只找到文本的内容
    # t_list = bs.find_all(text=['hao123', '贴吧', '新闻'])  # 还可以找多个
    # t_list = bs.find_all(text=re.compile('\d'))  # 还可以用正则表达式,把所有数字找出来
    # pprint(t_list)

    # 4.limit 参数
    # t_list = bs.find_all('a', limit=3)  # 限制获取多少个,标签
    # pprint(t_list)

    # css选择器
    # t_list = bs.select('title')  # 通过标签查找
    # t_list = bs.select('.mnav')  # 通过类名查找
    # t_list = bs.select('#u1')  # 通过id查找
    # t_list = bs.select('div > div')  # 通过子标签查找
    # pprint(t_list)
    t_list = bs.select('.mnav ~ .bri')  # 通过相邻兄弟选择器查找
    pprint(t_list)
    print(t_list[0].get_text())  # 只想要文本

    # 如果想要熟练爬虫，必须对以上内容非常熟悉才行